package p.ithorns.sample.office.excel;

import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.util.ConverterUtils;
import p.ithorns.framework.common.utils.JsonUtil;
import p.ithorns.framework.common.utils.StringUtil;

import java.util.*;

/**
 * MultiHeaderResolver
 * <p>
 * 多行头读取
 *
 * @author HtL
 * @date 2024/8/29 15:50
 * @since 1.0.0
 */
public class MultiHeaderResolver extends AnalysisEventListener<Object> {

    private final List<Map<Integer, String>> levelHeaders = new ArrayList<>(4);

    private final TreeMap<Integer, TreeMap<Integer, HeaderNode>> headerMatrix = new TreeMap<>();

    private List<HeaderNode> headerNodes;

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        Map<Integer, String> rowHeaders = ConverterUtils.convertToStringMap(headMap, context);
        final int rowIndex = context.readRowHolder().getRowIndex();

        levelHeaders.add(rowHeaders);

        Integer headRowNumber = context.readSheetHolder().getHeadRowNumber();
        if (rowIndex >= headRowNumber - 1) {
            synchronized (levelHeaders) {
                this.headerNodes = buildUniqueRootTree();
            }
        }
    }

    @Override
    public void invoke(Object data, AnalysisContext context) {
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        headerMatrix.clear();
        levelHeaders.clear();
    }

    public synchronized List<HeaderNode> getHeaderNodes() {
        return headerNodes;
    }

    /**
     * 构建唯一节点树
     * 如果下一层级找不到父节点，就报错
     */
    private List<HeaderNode> buildUniqueRootTree() {
        List<HeaderNode> nodeTree = new ArrayList<>();
        int levels = levelHeaders.size();
        for (int level = 0; level < levels; level++) {
            Map<Integer, String> headers = levelHeaders.get(level);
            Set<Map.Entry<Integer, String>> entries = headers.entrySet();

            // 上一个有效的node（所谓有效，就是HeaderName不为空）
            HeaderNode lastValidNode = null;
            for (Map.Entry<Integer, String> entry : entries) {
                String headerName = entry.getValue();
                // 加入到索引矩阵
                Integer columnIndex = entry.getKey();

                boolean isValidHeader = StringUtil.isNotBlank(headerName);
                if (isValidHeader) {
                    lastValidNode = new HeaderNode(level, columnIndex, headerName);
                }

                // 加入到列索引矩阵
                addIntoIndexes(level, columnIndex, lastValidNode);

                if (isValidHeader) {
                    // 根节点
                    if (level == 0) {
                        nodeTree.add(lastValidNode);
                    } else {
                        // 获取上一层的父节点
                        HeaderNode parent = getFromIndexes(level - 1, columnIndex);
                        if (null == parent) {
                            throw new RuntimeException("表头格式错误.");
                        } else {
                            parent.getChildren().add(lastValidNode);
                        }
                    }
                }
            }
        }
        return nodeTree;
    }

    /**
     * 构建多root节点树
     * 如果子节点找不到父节点，就独立出来，自己成父节点
     */
    private void buildMultiRootTree() {
        List<HeaderNode> nodeTree = new ArrayList<>();
        for (int i = 0; i < levelHeaders.size(); i++) {
            Map<Integer, String> headers = levelHeaders.get(i);
            Set<Map.Entry<Integer, String>> entries = headers.entrySet();

            HeaderNode lastEffectiveNode = null;
            for (Map.Entry<Integer, String> entry : entries) {
                String headerName = entry.getValue();

                // 加入到索引矩阵
                Integer columnIndex = entry.getKey();

                boolean isEffective = StringUtil.isNotBlank(headerName);
                if (isEffective) {
                    lastEffectiveNode = new HeaderNode(i, columnIndex, headerName);
                }
                addIntoIndexes(i, columnIndex, lastEffectiveNode);
                if (isEffective) {
                    // 根节点
                    if (i == 0) {
                        nodeTree.add(lastEffectiveNode);
                    } else {
                        // 子节点
                        HeaderNode parent = getFromIndexes(i - 1, columnIndex);
                        if (null == parent) {
                            // throw new RuntimeException("表头格式错误.");
                            nodeTree.add(lastEffectiveNode);
                        } else {
                            parent.getChildren().add(lastEffectiveNode);
                        }
                    }
                }
            }
        }

        System.out.println(JsonUtil.toJson(nodeTree));
    }

    private void addIntoIndexes(Integer rowIndex, Integer columnIndex, HeaderNode node) {
        TreeMap<Integer, HeaderNode> row = headerMatrix.computeIfAbsent(rowIndex, k -> new TreeMap<>());
        row.put(columnIndex, node);
    }

    private HeaderNode getFromIndexes(Integer rowIndex, Integer columnIndex) {
        TreeMap<Integer, HeaderNode> row = headerMatrix.get(rowIndex);
        if (null == row) {
            return null;
        }
        return row.get(columnIndex);
    }

}